<template>
  <div class="main-box">
    <TreeFilter title="部门列表" :is-all="false" :data="treeFilterData" :default-value="initParam.deptId" @change="changeTreeFilter" />
    <div class="table-box">
      <ProTable
        ref="proTable"
        row-key="userId"
        :indent="20"
        :columns="columns"
        :request-api="listUserApi"
        :request-auto="false"
        :init-param="initParam"
        :search-col="{ xs: 1, sm: 1, md: 2, lg: 3, xl: 3 }"
      >
        <!-- 表格 header 按钮 -->
        <template #tableHeader="scope">
          <el-button type="primary" v-auth="['system:user:add']" icon="CirclePlus" @click="openDialog(1, '用户新增')"> 新增 </el-button>
          <el-button type="primary" v-auth="['system:user:import']" icon="Upload" plain @click="batchAdd">导入</el-button>
          <el-button type="primary" v-auth="['system:user:export']" icon="Download" plain @click="downloadFile">导出</el-button>
          <el-button
            type="danger"
            v-auth="['system:user:remove']"
            icon="Delete"
            plain
            :disabled="!scope.isSelected"
            @click="batchDelete(scope.selectedListIds)"
          >
            批量删除
          </el-button>
        </template>
        <!-- 表格操作 -->
        <template #operation="scope">
          <el-button type="primary" link v-if="scope.row.userId !== 1" icon="EditPen" @click="openDialog(2, '用户编辑', scope.row)">编辑</el-button>
          <el-button type="primary" link v-if="scope.row.userId !== 1" icon="Delete" @click="deleteAccount(scope.row)">删除</el-button>
          <el-button type="primary" link v-if="scope.row.userId !== 1" icon="View" @click="handleResetPwd(scope.row)">重置密码</el-button>
        </template>
      </ProTable>
      <FormDialog ref="formDialogRef" :items-options="itemsOptions" :model="model" />
      <ImportExcel ref="dialogRef" />
      <TaskDialog ref="taskDialogRef" />
    </div>
  </div>
</template>

<script setup lang="tsx" name="UserManage">
import { User } from '@/api/interface'
import { useHandleData } from '@/hooks/useHandleData'
import { ElMessageBox, ElMessage } from 'element-plus'
// import { useDownload } from '@/hooks/useDownload'
import TreeFilter from '@/components/TreeFilter/index.vue'
import ImportExcel from '@/components/ImportExcel/index.vue'
import TaskDialog from '@/components/TaskDialog/index.vue'
import FormDialog from '@/components/FormDialog/index.vue'
import { ColumnProps, ProTableInstance } from '@/components/ProTable/interface'
import {
  listUserApi,
  delUserApi,
  addUserApi,
  updateUserApi,
  changeUserStatus,
  importTemplateApi,
  importDataApi,
  getUserApi,
  exportDownApi,
  deptTreeSelectApi,
  resetUserPwdApi
} from '@/api/modules/system/user'
const { proxy } = getCurrentInstance() as ComponentInternalInstance
const { sys_normal_disable, sys_user_gender } = toRefs<any>(proxy?.useDict('sys_normal_disable', 'sys_user_gender'))
onMounted(() => {
  getTreeFilter()
})

// ProTable 实例
const proTable = ref<ProTableInstance>()
// 表单model
const model = ref({})
// 如果表格需要初始化请求参数，直接定义传给 ProTable(之后每次请求都会自动带上该参数，此参数更改之后也会一直带上，改变此参数会自动刷新表格数据)
const initParam = reactive({ deptId: '' })

// 获取 treeFilter 数据
// 当 proTable 的 requestAuto 属性为 false，不会自动请求表格数据，等待 treeFilter 数据回来之后，更改 initParam.departmentId 的值，才会触发请求 proTable 数据
const treeFilterData = ref<any>([])
const getTreeFilter = async () => {
  const { data } = await deptTreeSelectApi()
  treeFilterData.value = data
  initParam.deptId = treeFilterData.value[0].id
}

// 树形筛选切换
const changeTreeFilter = (val: string) => {
  proTable.value!.pageable.pageNum = 1
  initParam.deptId = val
}

// 切换用户状态
const changeStatus = async (row: User.ResUserList) => {
  await useHandleData(changeUserStatus, { userId: row.userId, status: row.status == '1' ? 0 : 1 }, `切换【${row.userName}】用户状态`)
  proTable.value?.getTableList()
}

// 删除用户信息
const deleteAccount = async (params: User.ResUserList) => {
  await useHandleData(delUserApi, params.userId, `删除【${params.userName}】用户`)
  proTable.value?.getTableList()
}

// 批量删除用户信息
const batchDelete = async (ids: string[]) => {
  await useHandleData(delUserApi, ids, '删除所选用户信息')
  proTable.value?.clearSelection()
  proTable.value?.getTableList()
}

function handleResetPwd(row: any) {
  ElMessageBox.prompt('请输入"' + row.userName + '"的新密码', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    closeOnClickModal: false,
    inputPattern: /^.{5,20}$/,
    inputErrorMessage: '用户密码长度必须介于 5 和 20 之间'
  })
    .then(({ value }: any) => {
      resetUserPwdApi({ userId: row.userId, password: value }).then(res => {
        if (res.code == 200) ElMessage.success('修改成功，新密码是：' + value)
        else ElMessage.error(res.msg)
      })
    })
    .catch((e: any) => {
      console.log(e)
    })
}
const taskDialogRef = ref<InstanceType<typeof TaskDialog> | null>(null)
// 导出用户列表
const downloadFile = async () => {
  ElMessageBox.confirm('确认导出用户数据?', '温馨提示', { type: 'warning' }).then(async () => {
    exportDownApi(proTable.value?.searchParam)
    taskDialogRef.value?.openExportDialog()
  })
}

// 批量添加用户
const dialogRef = ref<InstanceType<typeof ImportExcel> | null>(null)
const batchAdd = () => {
  const params = {
    title: '用户',
    tempApi: importTemplateApi,
    importApi: importDataApi,
    getTableList: proTable.value?.getTableList
  }
  dialogRef.value?.acceptParams(params)
}
const formDialogRef = ref<InstanceType<typeof FormDialog> | null>(null)
const postOptions = ref<any[]>([])
const roleOptions = ref<any[]>([])
// 打开弹框的功能
const openDialog = async (type: number, title: string, row?: any) => {
  let res = await getUserApi(row?.userId || null)
  postOptions.value = res.data.posts
  roleOptions.value = res.data.roles
  // 表单项配置
  setItemsOptions()
  if (type == 1) {
    itemsOptions.splice(
      4,
      0,
      {
        label: '用户名称',
        prop: 'userName',
        span: 12,
        rules: [
          { required: true, message: '用户名称不能为空' },
          { min: 2, max: 20, message: '用户名称长度必须介于 2 和 20 之间', trigger: 'blur' }
        ],
        compOptions: {
          placeholder: '请输入用户名称'
        }
      },
      {
        label: '用户密码',
        prop: 'password',
        span: 12,
        rules: [
          { required: true, message: '密码不能为空' },
          { min: 5, max: 20, message: '用户密码长度必须介于 5 和 20 之间', trigger: 'blur' }
        ],
        compOptions: {
          showPassword: true,
          type: 'password',
          placeholder: '请输入密码'
        }
      }
    )
  }
  if (row?.userId) {
    res.data.user.postIds = res.data.postIds
    res.data.user.roleIds = res.data.roleIds
  }
  model.value = type == 1 ? {} : res.data.user
  const params = {
    title,
    width: 680,
    isEdit: type !== 3,
    api: type == 1 ? addUserApi : updateUserApi,
    getTableList: proTable.value?.getTableList
  }

  formDialogRef.value?.openDialog(params)
}
// 表格配置项
const columns = reactive<ColumnProps<User.ResUserList>[]>([
  { type: 'selection', fixed: 'left', width: 60 },
  { prop: 'userId', label: '用户编号', width: 100 },
  { prop: 'userName', label: '用户名称', search: { el: 'input' }, width: 120 },
  { prop: 'nickName', label: '用户昵称', search: { el: 'input' }, width: 120 },
  { prop: 'dept.deptName', label: '部门', width: 120 },
  { prop: 'phonenumber', label: '手机号码', width: 120 },
  {
    prop: 'status',
    label: '用户状态',
    width: 120,
    enum: sys_normal_disable,
    search: { el: 'tree-select' },
    render: scope => {
      return (
        <el-switch
          model-value={scope.row.status}
          active-text={scope.row.status === '0' ? '禁用' : '启用'}
          active-value={'1'}
          inactive-value={'0'}
          onClick={() => changeStatus(scope.row)}
        />
      )
    }
  },
  {
    prop: 'gender',
    label: '性别',
    width: 120,
    enum: sys_user_gender
  },
  { prop: 'createTime', label: '创建时间', width: 180 },
  { prop: 'operation', label: '操作', width: 240, fixed: 'right' }
])
// 表单配置项
let itemsOptions = reactive<ProForm.ItemsOptions[]>([])
const setItemsOptions = () => {
  itemsOptions = [
    {
      label: '用户昵称',
      span: 12,
      prop: 'nickName',
      rules: [{ required: true, message: '用户昵称不能为空' }],
      compOptions: {
        placeholder: '请输入用户昵称'
      }
    },
    {
      label: '归属部门',
      span: 12,
      prop: 'deptId',
      compOptions: {
        elTagName: 'tree-select',
        enum: () => deptTreeSelectApi(),
        valueKey: 'id',
        labelKey: 'label',
        checkStrictly: true,
        placeholder: '请选择归属部门'
      }
    },
    {
      label: '手机号码',
      span: 12,
      prop: 'phonenumber',
      rules: [{ pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/, message: '请输入正确的手机号码', trigger: 'blur' }],
      compOptions: {
        placeholder: '请输入手机号码'
      }
    },
    {
      label: '邮箱',
      span: 12,
      prop: 'email',
      rules: [{ type: 'email', message: '请输入正确的邮箱地址', trigger: ['blur', 'change'] }],
      compOptions: {
        placeholder: '请输入邮箱'
      }
    },
    {
      label: '性别',
      span: 12,
      prop: 'gender',
      compOptions: {
        elTagName: 'radio-group',
        enum: sys_user_gender.value,
        placeholder: '请输入邮箱'
      }
    },
    {
      label: '状态',
      span: 12,
      prop: 'status',
      compOptions: {
        elTagName: 'radio-group',
        value: '1',
        enum: sys_normal_disable.value
      }
    },
    {
      label: '岗位',
      span: 12,
      prop: 'postIds',
      compOptions: {
        elTagName: 'select',
        valueKey: 'postId',
        labelKey: 'postName',
        multiple: true,
        enum: postOptions.value,
        placeholder: '请选择岗位'
      }
    },
    {
      label: '角色',
      span: 12,
      prop: 'roleIds',
      compOptions: {
        elTagName: 'select',
        enum: roleOptions.value,
        valueKey: 'roleId',
        labelKey: 'roleName',
        multiple: true
      }
    },
    {
      label: '备注',
      prop: 'remark',
      compOptions: {
        type: 'textarea',
        placeholder: '请输入内容'
      }
    }
  ]
}
</script>
